/***************************************************************************************************
  *Copyright(C),2010-2017,Sumscope
  *FileName	:  ProtoAdaptor.h
  *Author	:  scofined.qi
  *Version	:  1.0
  *Date		:  2019/01/17
  *Desc		:  //用于主要说明此程序文件完成的主要功能
  *Relation :  
  *Others	:  //其他内容说明
  *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
  *History	:  //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
***************************************************************************************************/
#ifndef PROTOADAPTOR_H_4FDD1B8A_A3F5_4FBB_92DA_6248CDE36278
#define PROTOADAPTOR_H_4FDD1B8A_A3F5_4FBB_92DA_6248CDE36278

#include "proto_message.h"
#include "variant.h"
#include "message.h"

namespace qb{
	namespace net{
		typedef qb::proto::int8_t int8_t;
		typedef qb::proto::uint8_t uint8_t;
		typedef qb::proto::uint16_t uint16_t;
		typedef qb::proto::int16_t int16_t;
		typedef qb::proto::uint32_t uint32_t;
		typedef qb::proto::int32_t int32_t;
		typedef qb::proto::uint64_t uint64_t;
		typedef qb::proto::int64_t int64_t;

		class ProtoList{
		public:
			typedef qb::proto::Variant Variant;
			typedef qb::proto::Message::List List;
			typedef qb::proto::Message Message;
			typedef qb::proto::Message::List::iterator iterator;
			typedef qb::proto::Message::List::const_iterator const_iterator;
			friend class ProtoMap;
			friend class ProtoMessage;
		private:
			const List*	m_list;
		private:
			ProtoList(const ProtoList& pm) = delete;
			ProtoList& operator=(const ProtoList& pm) = delete;
			void SetList(const List* list){ m_list = list; }
		public:
			ProtoList();
			//ProtoList(const List* list);
			ProtoList(const Variant& v);
			bool RefListFrom(const Message& msg, const char* name);
			const_iterator begin()const;
			const_iterator end()const;
			int size()const{ return m_list ? m_list->size() : 0; }
			void clear(){ m_list = nullptr; }
		};
		class ProtoMap{
		public:
			typedef qb::proto::Variant Variant;
			typedef qb::proto::Message::List List;
			typedef qb::proto::VariantMap VariantMap;
			typedef qb::proto::Message Message;
			typedef qb::proto::Message::List::iterator iterator;
			typedef qb::proto::Message::List::const_iterator const_iterator;
			friend class ProtoMessage;
		private:
			const VariantMap*	m_map;
			std::vector<ProtoList*>	m_reflist;
		private:
			ProtoMap(const ProtoMap& pm) = delete;
			ProtoMap& operator=(const ProtoMap& pm) = delete;
			void SetMap(const VariantMap* map){ m_map = map; }
		public:
			ProtoMap();
			//ProtoMap(const VariantMap* map);
			ProtoMap(const Variant& v);
			~ProtoMap();
			bool RefList(const char* name,const ProtoList*& pList)const;
			bool RefMapFrom(const Message& msg, const char* name);
			bool GetList(const char* name, ProtoList& list)const;
			bool getList(const char* name, ProtoList& list)const;
			bool GetMap(const char* name, ProtoMap& map)const;
			bool RefString(const char *name, const char *& value, size_t &size) const;
			operator const VariantMap&()const;

#define IMPL_GET_MAP_PROPERTY(NAME,VAL,FUNC) return m_map ? m_map->FUNC(NAME,VAL) :false;
			bool GetBool(const char *name, bool &value) const{ IMPL_GET_MAP_PROPERTY(name, value, GetBool); }
			bool GetUInt8(const char *name, uint8_t &value) const{ IMPL_GET_MAP_PROPERTY(name, value, GetUInt8); }
			bool GetUInt16(const char *name, uint16_t &value) const{ IMPL_GET_MAP_PROPERTY(name, value, GetUInt16); }
			bool GetUInt32(const char *name, uint32_t &value) const{ IMPL_GET_MAP_PROPERTY(name, value, GetUInt32); }
			bool GetUInt64(const char *name, uint64_t &value) const{ IMPL_GET_MAP_PROPERTY(name, value, GetUInt64); }
			bool GetInt8(const char *name, int8_t &value) const{ IMPL_GET_MAP_PROPERTY(name, value, GetInt8); }
			bool GetInt16(const char *name, int16_t &value) const{ IMPL_GET_MAP_PROPERTY(name, value, GetInt16); }
			bool GetInt32(const char *name, int32_t &value) const{ IMPL_GET_MAP_PROPERTY(name, value, GetInt32); }
			bool GetInt64(const char *name, int64_t &value) const{ IMPL_GET_MAP_PROPERTY(name, value, GetInt64); }
			bool GetFloat(const char *name, float &value) const{ IMPL_GET_MAP_PROPERTY(name, value, GetFloat); }
			bool GetDouble(const char *name, double &value) const{ IMPL_GET_MAP_PROPERTY(name, value, GetDouble); }
			

			inline bool getBool(const std::string& name, bool &value) const { return GetBool(name.c_str(), value); }
			inline bool getUint8(const std::string& name, uint8_t &value) const { return GetUInt8(name.c_str(), value); }
			inline bool getUint16(const std::string& name, uint16_t &value) const { return GetUInt16(name.c_str(), value); }
			inline bool getUint32(const std::string& name, uint32_t &value) const { return GetUInt32(name.c_str(), value); }
			inline bool getUint64(const std::string& name, uint64_t &value) const { return GetUInt64(name.c_str(), value); }
			inline bool getInt8(const std::string& name, int8_t &value) const { return GetInt8(name.c_str(), value); }
			inline bool getInt16(const std::string& name, int16_t &value) const { return GetInt16(name.c_str(), value); }
			inline bool getInt32(const std::string& name, int32_t &value) const { return GetInt32(name.c_str(), value); }
			inline bool getInt64(const std::string& name, int64_t &value) const { return GetInt64(name.c_str(), value); }
			inline bool getFloat(const std::string& name, float &value) const { return GetFloat(name.c_str(), value); }
			inline bool getDouble(const std::string& name, double &value) const { return GetDouble(name.c_str(), value); }
		};
		class ProtoMessage{
			typedef qb::proto::Message Message;
			typedef qb::proto::Message::Raw Raw;
			typedef qb::proto::VariantMap	VariantMap;
			const Message*		m_message;
			const VariantMap*	m_map;			// 参考MessageParser::ExtractData,
												// 这两个成员只能有一个有效
		public:
			ProtoMessage(const Message& msg);
			ProtoMessage(const ProtoMap& map);
			//bool RefMsgFrom(const Message& msg, const char* name){
			//	msg.getMessage()
			//}
			bool GetList(const char* name, ProtoList& list)const;
			const ProtoMap& MapValue();
			bool GetRaw(const char *name, Raw& value) const;

#define IMPL_GET_PROPERTY(NAME,VAL,FUNC) if (m_message == nullptr && m_map == nullptr)return false;\
			return m_message ? m_message->FUNC(NAME,VAL) :m_map->FUNC(NAME,VAL);

			bool getList(const char* name, ProtoList& list)const;
			bool GetMap(const char* name, ProtoMap& map)const;
			bool RefString(const char *name, const char *& value, size_t &size) const;

			bool GetBool(const char *name, bool &value) const{IMPL_GET_PROPERTY(name, value, GetBool);}
			bool GetUInt8(const char *name, uint8_t &value) const{IMPL_GET_PROPERTY(name, value, GetUInt8);}
			bool GetUInt16(const char *name, uint16_t &value) const{IMPL_GET_PROPERTY(name, value, GetUInt16);}
			bool GetUInt32(const char *name, uint32_t &value) const{IMPL_GET_PROPERTY(name, value, GetUInt32);}
			bool GetUInt64(const char *name, uint64_t &value) const{IMPL_GET_PROPERTY(name, value, GetUInt64);}
			bool GetInt8(const char *name, int8_t &value) const{IMPL_GET_PROPERTY(name, value, GetInt8);}
			bool GetInt16(const char *name, int16_t &value) const{IMPL_GET_PROPERTY(name, value, GetInt16);}
			bool GetInt32(const char *name, int32_t &value) const{IMPL_GET_PROPERTY(name, value, GetInt32);}
			bool GetInt64(const char *name, int64_t &value) const{IMPL_GET_PROPERTY(name, value, GetInt64);}
			bool GetFloat(const char *name, float &value) const{IMPL_GET_PROPERTY(name, value, GetFloat);}
			bool GetDouble(const char *name, double &value) const{IMPL_GET_PROPERTY(name, value, GetDouble);}
			inline bool getBool(const std::string& name, bool &value) const { return GetBool(name.c_str(), value); }
			inline bool getUint8(const std::string& name, uint8_t &value) const { return GetUInt8(name.c_str(), value); }
			inline bool getUint16(const std::string& name, uint16_t &value) const { return GetUInt16(name.c_str(), value); }
			inline bool getUint32(const std::string& name, uint32_t &value) const { return GetUInt32(name.c_str(), value); }
			inline bool getUint64(const std::string& name, uint64_t &value) const { return GetUInt64(name.c_str(), value); }
			inline bool getInt8(const std::string& name, int8_t &value) const { return GetInt8(name.c_str(), value); }
			inline bool getInt16(const std::string& name, int16_t &value) const { return GetInt16(name.c_str(), value); }
			inline bool getInt32(const std::string& name, int32_t &value) const { return GetInt32(name.c_str(), value); }
			inline bool getInt64(const std::string& name, int64_t &value) const { return GetInt64(name.c_str(), value); }
			inline bool getFloat(const std::string& name, float &value) const { return GetFloat(name.c_str(), value); }
			inline bool getDouble(const std::string& name, double &value) const { return GetDouble(name.c_str(), value); }
		};
	}// namespace net
}//namespace qb

namespace qb{
	namespace base{
		namespace msg{
			class ProtoUtil{
			public:
				static bool CheckMessage(const ProtoMessage& msg, const char* buf, int len);
			};
		}
	}
}

#define USING_PROTO_ADAPTOR
#ifdef USING_PROTO_ADAPTOR
#define REFMAP_FROM_MSG(MSG,NAME,MAP)	MAP.RefMapFrom(MSG,NAME)
#define REFLIST_FROM_MSG(MSG,NAME,LIST)	LIST.RefListFrom(MSG,NAME)
#define WrapProtoMsg(MSG)	MSG
typedef qb::base::msg::ProtoMap ProtoMap;
typedef qb::base::msg::ProtoList ProtoList;
typedef qb::base::msg::ProtoMessage ProtoMessage;
typedef qb::base::msg::Raw ProtoRaw;
typedef qb::base::msg::Value ProtoValue;
#else
#define REFMAP_FROM_MSG(MSG,NAME,MAP)	MSG.GetMap(NAME,MAP)
#define REFLIST_FROM_MSG(MSG,NAME,LIST)	MSG.getList(NAME,LIST)
#define WrapProtoMsg(MSG)	MSG
typedef qb::proto::Message ProtoMessage;
typedef qb::proto::VariantMap ProtoMap;
typedef qb::proto::Message::List ProtoList;
typedef qb::proto::Message::Raw ProtoRaw;
typedef qb::proto::Variant ProtoValue;

#endif

#endif
